#include "stdafx.h"
#include <winreg.h>
#include "Registry.h"
#include "ImpersonateUser.h"

CRegistry::CRegistry()
{
	m_hRootKey = HKEY_CURRENT_USER;
	m_bLazyWrite = TRUE;
	m_bUseWwow64 = FALSE;
	m_nLastError = ERROR_SUCCESS;
}

CRegistry::~CRegistry()
{
	ClearKey();
}

BOOL CRegistry::ClearKey()
{
	m_strCurrentPath.Empty();
	m_hRootKey = HKEY_CURRENT_USER;
	m_bLazyWrite = TRUE;
	return TRUE;
}

BOOL CRegistry::SetRootKey(HKEY hRootKey)
{
	if ( hRootKey != HKEY_CLASSES_ROOT &&
		 hRootKey != HKEY_CURRENT_USER &&
		 hRootKey != HKEY_LOCAL_MACHINE &&
		 hRootKey != HKEY_USERS )
	{
		return FALSE;
	}

	m_hRootKey = hRootKey;
	return TRUE;
}

HKEY CRegistry::GetRootKeyEx()
{
	HKEY hRetKey = m_hRootKey;
	if ( m_hRootKey == HKEY_CURRENT_USER )
	{
		CImpersonateUser impersonate;
		HKEY hSoftKey = NULL;
		if ( RegOpenCurrentUser(KEY_READ, &hSoftKey) == ERROR_SUCCESS )
		{
			hRetKey = hSoftKey;
		}
	}

	return hRetKey;
}

void CRegistry::CloseRootKeyEx(HKEY &hRootKey)
{
	if ( hRootKey != HKEY_CLASSES_ROOT &&
		 hRootKey != HKEY_CURRENT_USER &&
		 hRootKey != HKEY_LOCAL_MACHINE &&
		 hRootKey != HKEY_USERS )
	{
		RegCloseKey(hRootKey);
	}
}

BOOL CRegistry::CreateKey(LPCTSTR strKey)
{
	ASSERT(strKey[0] != '\\');
	HKEY hKey, hRootKey = GetRootKeyEx();
	DWORD dwDisposition = 0;
	REGSAM desire = KEY_ALL_ACCESS;
	if ( m_bUseWwow64 )
	{
		desire |= KEY_WOW64_64KEY;
	}

	if ( ::RegCreateKeyEx(hRootKey, strKey, 0, NULL, REG_OPTION_NON_VOLATILE, desire, NULL, &hKey, &dwDisposition) != ERROR_SUCCESS )
	{
		CloseRootKeyEx(hRootKey);
		return FALSE;
	}

	if ( !m_bLazyWrite )
	{
		::RegFlushKey(hKey);
	}

	::RegCloseKey(hKey);
	CloseRootKeyEx(hRootKey);

	m_strCurrentPath = strKey;
	return TRUE;
}

BOOL CRegistry::DeleteKey(LPCTSTR strKey)
{
	ASSERT(strKey[0] != '\\');

	if ( !KeyExists(strKey) )
	{
		return TRUE;
	}

	HKEY hRootKey = GetRootKeyEx();
	if ( ::RegDeleteKey(hRootKey, strKey) != ERROR_SUCCESS )
	{
		CloseRootKeyEx(hRootKey);
		return FALSE;
	}

	CloseRootKeyEx(hRootKey);
	return TRUE;
}

BOOL CRegistry::DeleteValue(LPCTSTR strName)
{
	ASSERT( m_strCurrentPath.GetLength() > 0 );
	HKEY hKey, hRootKey = GetRootKeyEx();
	REGSAM desire = KEY_SET_VALUE;
	if ( m_bUseWwow64 )
	{
		desire |= KEY_WOW64_64KEY;
	}

	if ( ::RegOpenKeyEx(hRootKey, LPCTSTR(m_strCurrentPath), 0, desire, &hKey) != ERROR_SUCCESS )
	{
		CloseRootKeyEx(hRootKey);
		return FALSE;
	}

	LONG lResult = ::RegDeleteValue(hKey, strName);
	::RegCloseKey(hKey);
	CloseRootKeyEx(hRootKey);

	if ( lResult == ERROR_SUCCESS )
	{
		return TRUE;
	}

	return FALSE;
}

int CRegistry::GetDataSize(LPCTSTR strValueName)
{
	ASSERT(m_strCurrentPath.GetLength() > 0);
	HKEY hKey, hRootKey = GetRootKeyEx();
	LONG lResult;
	REGSAM desire = KEY_QUERY_VALUE;
	if ( m_bUseWwow64 )
	{
		desire |= KEY_WOW64_64KEY;
	}

	if ( ::RegOpenKeyEx(hRootKey, LPCTSTR(m_strCurrentPath), 0, desire, &hKey) != ERROR_SUCCESS )
	{
		CloseRootKeyEx(hRootKey);
		return -1;
	}

	DWORD dwSize = 1;
	lResult = ::RegQueryValueEx(hKey, strValueName, NULL, NULL, NULL, &dwSize);
	::RegCloseKey(hKey);
	CloseRootKeyEx(hRootKey);

	if ( lResult != ERROR_SUCCESS )
	{
		return -1;
	}

	return (int)dwSize;
}

DWORD CRegistry::GetDataType(LPCTSTR strValueName, LPCTSTR strSubKey)
{
//	ASSERT(m_strCurrentPath.GetLength() > 0);
	HKEY hKey, hRootKey = GetRootKeyEx();
	CString strkeyPath = m_strCurrentPath;
	if ( _tcslen(strSubKey) > 0 )
	{
		strkeyPath += _T("\\") + CString(strSubKey);
	}

	REGSAM desire = KEY_QUERY_VALUE;
	if ( m_bUseWwow64 )
	{
		desire |= KEY_WOW64_64KEY;
	}
	m_nLastError = ::RegOpenKeyEx(hRootKey, LPCTSTR(strkeyPath), 0, desire, &hKey);

	if (m_nLastError != ERROR_SUCCESS)
	{
		CloseRootKeyEx(hRootKey);
		return 0;
	}

	DWORD dwType = 1;
	m_nLastError = ::RegQueryValueEx(hKey, (LPCTSTR)strValueName, NULL, &dwType, NULL, NULL);
	::RegCloseKey(hKey);		
	CloseRootKeyEx(hRootKey);

	if ( m_nLastError == ERROR_SUCCESS )
	{
		return dwType;
	}

	return 0;
}

int CRegistry::GetSubKeyCount()
{
	//	ASSERT(m_strCurrentPath.GetLength() > 0);
	HKEY hKey, hRootKey = GetRootKeyEx();
	REGSAM desire = KEY_ALL_ACCESS;
	if ( m_bUseWwow64 )
	{
		desire |= KEY_WOW64_64KEY;
	}
	if ( ::RegOpenKeyEx(hRootKey, LPCTSTR(m_strCurrentPath), 0, desire, &hKey) != ERROR_SUCCESS )
	{
		CloseRootKeyEx(hRootKey);
		return -1;
	}

	LONG lResult;
	DWORD dwSubKeyCount, dwValueCount, dwMaxSubKeyName, dwMaxValueName, dwMaxValueLength;
	DWORD dwClassNameLength = MAX_PATH;
	TCHAR szClassBuffer[MAX_PATH] = {0};
	FILETIME ftLastWritten;	

	lResult = ::RegQueryInfoKey(hKey, szClassBuffer, &dwClassNameLength, NULL, &dwSubKeyCount, &dwMaxSubKeyName, NULL, &dwValueCount, &dwMaxValueName, &dwMaxValueLength, NULL, &ftLastWritten);
	::RegCloseKey(hKey);
	CloseRootKeyEx(hRootKey);

	if ( lResult != ERROR_SUCCESS )
	{
		return -1;
	}

	return (int)dwSubKeyCount;
}

BOOL CRegistry::GetSubKey(int nIndex, CString &strSubKey)
{
	//	ASSERT(m_strCurrentPath.GetLength() > 0);
	HKEY hKey, hRootKey = GetRootKeyEx();
	REGSAM desire = KEY_ALL_ACCESS;
	if ( m_bUseWwow64 )
	{
		desire |= KEY_WOW64_64KEY;
	}
	strSubKey.Empty();
	if ( ::RegOpenKeyEx(hRootKey, LPCTSTR(m_strCurrentPath), 0, desire, &hKey) == ERROR_SUCCESS && nIndex >=0 )
	{
		TCHAR szKeyName[MAX_PATH+1] = {0};
		if ( RegEnumKey(hKey, nIndex, szKeyName, MAX_PATH) == ERROR_SUCCESS )
		{
			strSubKey = szKeyName;
		}

		::RegCloseKey(hKey);
	}

	CloseRootKeyEx(hRootKey);
	return (strSubKey.GetLength() > 0) ? TRUE : FALSE;
}

int CRegistry::GetValueCount(LPCTSTR strSubKey)
{
	ASSERT(m_strCurrentPath.GetLength() > 0);
	HKEY hKey, hRootKey = GetRootKeyEx();
	CString strkeyPath = m_strCurrentPath;

	if ( _tcslen(strSubKey) > 0 )
	{
		strkeyPath += _T("\\") + CString(strSubKey);
	}
	REGSAM desire = KEY_ALL_ACCESS;
	if ( m_bUseWwow64 )
	{
		desire |= KEY_WOW64_64KEY;
	}
	if ( ::RegOpenKeyEx(hRootKey, LPCTSTR(strkeyPath), 0,	desire, &hKey) != ERROR_SUCCESS )
	{
		CloseRootKeyEx(hRootKey);
		return -1;
	}

	LONG lResult;
	DWORD dwSubKeyCount, dwValueCount, dwMaxSubKeyName, dwMaxValueName, dwMaxValueLength;
	DWORD dwClassNameLength = MAX_PATH;
	TCHAR szClassBuffer[MAX_PATH] = {0};
	FILETIME ftLastWritten;

	lResult = ::RegQueryInfoKey(hKey, szClassBuffer, &dwClassNameLength, NULL, &dwSubKeyCount, &dwMaxSubKeyName, NULL, &dwValueCount, &dwMaxValueName, &dwMaxValueLength, NULL, &ftLastWritten);
	::RegCloseKey(hKey);
	CloseRootKeyEx(hRootKey);

	if ( lResult != ERROR_SUCCESS )
	{
		return -1;
	}

	return (int)dwValueCount;
}

CString CRegistry::GetValueName(int nIndex, LPCTSTR strSubKey)
{
	HKEY hKey, hRootKey = GetRootKeyEx();
	ASSERT(m_strCurrentPath.GetLength() > 0);

	CString strkeyPath = m_strCurrentPath;
	if ( _tcslen(strSubKey) )
	{
		strkeyPath += _T("\\") + CString(strSubKey);
	}
	REGSAM desire = KEY_ALL_ACCESS;
	if ( m_bUseWwow64 )
	{
		desire |= KEY_WOW64_64KEY;
	}
	CString strValueName;
	if ( ::RegOpenKeyEx(hRootKey, LPCTSTR(strkeyPath), 0, desire, &hKey) == ERROR_SUCCESS && nIndex >= 0 )
	{
		DWORD dwValueNameSize = MAX_PATH;
		TCHAR szValueName[MAX_PATH+1] = {_T("")};
		if ( RegEnumValue(hKey, nIndex, szValueName, &dwValueNameSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS )
		{
			strValueName = szValueName;
		}
		::RegCloseKey(hKey);
	}

	CloseRootKeyEx(hRootKey);
	return strValueName;
}

BOOL CRegistry::KeyExists(LPCTSTR strKey, HKEY hRootKey)
{
	ASSERT(strKey[0] != '\\');
	HKEY hKey;
	BOOL bUseRoot = FALSE;

	if ( hRootKey == NULL )
	{
		hRootKey = GetRootKeyEx();
		bUseRoot = TRUE;
	}

	REGSAM desire = KEY_ALL_ACCESS;
	if ( m_bUseWwow64 )
	{
		desire |= KEY_WOW64_64KEY;
	}

	LONG lResult = ::RegOpenKeyEx(hRootKey, strKey, 0, desire, &hKey);
	::RegCloseKey(hKey);
	
	if ( bUseRoot )
	{
		CloseRootKeyEx(hRootKey);
	}

	if ( lResult == ERROR_SUCCESS )
	{
		return TRUE;
	}
	return FALSE;
}

BOOL CRegistry::SetKey(LPCTSTR strKey, BOOL bCanCreate)
{
	ASSERT(strKey[0] != '\\');
	HKEY hKey, hRootKey = GetRootKeyEx();

	if ( _tcslen(strKey) == 0 )
	{
		m_strCurrentPath.Empty();
		return TRUE;
	}

	REGSAM desire = KEY_ALL_ACCESS;
	if ( m_bUseWwow64 )
	{
		desire |= KEY_WOW64_64KEY;
	}
	if ( bCanCreate )
	{
		DWORD dwDisposition = 0;
		if ( ::RegCreateKeyEx(hRootKey, strKey, 0, NULL, REG_OPTION_NON_VOLATILE, desire, NULL, &hKey, &dwDisposition) != ERROR_SUCCESS )
		{
			CloseRootKeyEx(hRootKey);
			return FALSE;
		}
		m_strCurrentPath = strKey;
		
		if ( !m_bLazyWrite )
		{
			::RegFlushKey(hKey);
		}

		::RegCloseKey(hKey);
		CloseRootKeyEx(hRootKey);
		return TRUE;
	}

	if ( bCanCreate )
	{
		m_nLastError = ::RegOpenKeyEx(hRootKey, LPCTSTR(strKey), 0, desire, &hKey);
	}
	else
	{
		desire = KEY_READ;
		if ( m_bUseWwow64 )
		{
			desire |= KEY_WOW64_64KEY;
		}

		m_nLastError = ::RegOpenKeyEx(hRootKey, LPCTSTR(strKey), 0, desire, &hKey);
	}

	if ( m_nLastError != ERROR_SUCCESS )
	{
		CloseRootKeyEx(hRootKey);
		return FALSE;
	}

	m_strCurrentPath = strKey;

	if ( !m_bLazyWrite )
	{
		::RegFlushKey(hKey);
	}
	::RegCloseKey(hKey);
	CloseRootKeyEx(hRootKey);

	return TRUE;
}


BOOL CRegistry::ValueExists(LPCTSTR strName)
{
	HKEY hKey, hRootKey = GetRootKeyEx();
	ASSERT(m_strCurrentPath.GetLength() > 0);
	REGSAM desire = KEY_ALL_ACCESS;
	if ( m_bUseWwow64 )
	{
		desire |= KEY_WOW64_64KEY;
	}
	if ( ::RegOpenKeyEx(hRootKey, LPCTSTR(m_strCurrentPath), 0, desire, &hKey) != ERROR_SUCCESS)
	{
		CloseRootKeyEx(hRootKey);
		return FALSE;
	}

	LONG lResult = ::RegQueryValueEx(hKey, strName, NULL, NULL, NULL, NULL);
	::RegCloseKey(hKey);
	CloseRootKeyEx(hRootKey);

	if ( lResult == ERROR_SUCCESS )
	{
		return TRUE;
	}

	return FALSE;
}

double CRegistry::ReadFloat(LPCTSTR strName, double fDefault)
{
	double d;
	DWORD dwType = REG_BINARY;
	DWORD dwSize = sizeof(d);
	HKEY hKey, hRootKey = GetRootKeyEx();

	ASSERT(m_strCurrentPath.GetLength() > 0);
	REGSAM desire = KEY_READ;
	if ( m_bUseWwow64 )
	{
		desire |= KEY_WOW64_64KEY;
	}
	if ( ::RegOpenKeyEx(hRootKey, LPCTSTR(m_strCurrentPath), 0, desire, &hKey) != ERROR_SUCCESS )
	{
		CloseRootKeyEx(hRootKey);
		return fDefault;
	}

	if ( ::RegQueryValueEx(hKey, LPCTSTR(strName), NULL, &dwType, (LPBYTE)&d, &dwSize) != ERROR_SUCCESS )
	{
		d = fDefault;
	}
	::RegCloseKey(hKey);
	CloseRootKeyEx(hRootKey);

	return d;
}

BOOL CRegistry::ReadBinary(LPCTSTR lpszEntry, LPBYTE* ppData, UINT* pBytes)
{
	BOOL bRc = FALSE;
	ASSERT(lpszEntry != NULL);
	ASSERT(ppData != NULL);
	ASSERT(pBytes != NULL);
	*ppData = NULL;
	*pBytes = 0;

	if ( !m_strCurrentPath.IsEmpty() )
	{
		HKEY hKey, hRootKey = GetRootKeyEx();
		ASSERT(m_strCurrentPath.GetLength() > 0);
		REGSAM desire = KEY_READ;
		if ( m_bUseWwow64 )
		{
			desire |= KEY_WOW64_64KEY;
		}
		if ( ::RegOpenKeyEx(hRootKey, LPCTSTR(m_strCurrentPath), 0, desire, &hKey) == ERROR_SUCCESS )
		{
			DWORD dwType = 0, dwCount=0; 
			LONG lResult = RegQueryValueEx(hKey, (LPTSTR)lpszEntry, NULL, &dwType, NULL, &dwCount);
			*pBytes = dwCount;
			if ( lResult == ERROR_SUCCESS )
			{
				ASSERT(dwType == REG_BINARY);
				*ppData = new BYTE[*pBytes];
				lResult = RegQueryValueEx(hKey, (LPTSTR)lpszEntry, NULL, &dwType, *ppData, &dwCount);
			}
			if ( lResult == ERROR_SUCCESS )
			{
				ASSERT(dwType == REG_BINARY);
				bRc = TRUE;
			}
			else
			{
				delete [] *ppData;
				*ppData = NULL;
			}
			::RegCloseKey(hKey);
		}
		CloseRootKeyEx(hRootKey);
	}

	return bRc;
}

CString CRegistry::ReadString(LPCTSTR strName, LPCTSTR strDefault, LPCTSTR strSubKey)
{
	BOOL bSuccess = TRUE;
	DWORD dwType = REG_SZ, dwSize = 2048;
	TCHAR sz[2048];
	HKEY hKey;
							 
//	ASSERT(m_strCurrentPath.GetLength() > 0);

	CString strkeyPath = m_strCurrentPath;
	if ( _tcslen(strSubKey) )
	{
		strkeyPath += _T("\\") + CString(strSubKey);
	}

	dwType = GetDataType(strName, strSubKey);
	
	if ( dwType != REG_SZ && dwType != REG_EXPAND_SZ )
	{
		return CString(strDefault);
	}

	HKEY hRootKey = GetRootKeyEx();
	REGSAM desire = KEY_READ;
	if ( m_bUseWwow64 )
	{
		desire |= KEY_WOW64_64KEY;
	}
	m_nLastError = ::RegOpenKeyEx(hRootKey, LPCTSTR(strkeyPath), 0, desire, &hKey);
	if ( m_nLastError != ERROR_SUCCESS )
	{
		CloseRootKeyEx(hRootKey);
		return strDefault;
	}

	m_nLastError = ::RegQueryValueEx(hKey, strName, NULL, &dwType, (LPBYTE)sz, &dwSize);
	if ( m_nLastError != ERROR_SUCCESS )
	{
		bSuccess = FALSE;
	}
	::RegCloseKey(hKey);	
	CloseRootKeyEx(hRootKey);

	if ( !bSuccess )
	{
		return strDefault;
	}

	return CString(sz);
}

string CRegistry::ReadString1(LPCTSTR strName, LPCTSTR strDefault, LPCTSTR strSubKey)
{
	BOOL bSuccess = TRUE;
	DWORD dwType = REG_SZ, dwSize = 2048;
	TCHAR sz[2048];
	HKEY hKey;
	USES_CONVERSION;
	string strRet = T2A(strDefault);

	ASSERT(m_strCurrentPath.GetLength() > 0);

	CString strkeyPath = m_strCurrentPath;
	if ( _tcslen(strSubKey) )
	{
		strkeyPath += _T("\\") + CString(strSubKey);
	}

	dwType = GetDataType(strName, strSubKey);

	if ( dwType != REG_SZ && dwType != REG_EXPAND_SZ )
	{
		return strRet;
	}

	HKEY hRootKey = GetRootKeyEx();
	REGSAM desire = KEY_READ;
	if ( m_bUseWwow64 )
	{
		desire |= KEY_WOW64_64KEY;
	}
	m_nLastError = ::RegOpenKeyEx(hRootKey, LPCTSTR(strkeyPath), 0, desire, &hKey);
	if ( m_nLastError != ERROR_SUCCESS )
	{
		CloseRootKeyEx(hRootKey);
		return strRet;
	}

	m_nLastError = ::RegQueryValueEx(hKey, strName, NULL, &dwType, (LPBYTE)sz, &dwSize);
	if ( m_nLastError != ERROR_SUCCESS )
	{
		bSuccess = FALSE;
	}
	::RegCloseKey(hKey);	
	CloseRootKeyEx(hRootKey);

	if ( !bSuccess )
	{
		return strRet;
	}

	strRet = T2A(sz);
	return strRet;
}

DWORD CRegistry::ReadDword(LPCTSTR strName, DWORD dwDefault)
{
	DWORD dwType = REG_DWORD;
	DWORD dw;
	DWORD dwSize = sizeof(dw);
	HKEY hKey, hRootKey = GetRootKeyEx();

//	ASSERT(m_strCurrentPath.GetLength() > 0);
	REGSAM desire = KEY_READ;
	if ( m_bUseWwow64 )
	{
		desire |= KEY_WOW64_64KEY;
	}
	if ( ::RegOpenKeyEx(hRootKey, LPCTSTR(m_strCurrentPath), 0, desire, &hKey) != ERROR_SUCCESS )
	{
		CloseRootKeyEx(hRootKey);
		return dwDefault;
	}

	if ( ::RegQueryValueEx(hKey, strName, NULL, &dwType, (LPBYTE)&dw, &dwSize) != ERROR_SUCCESS )
	{
		dw = dwDefault;
	}

	::RegCloseKey(hKey);
	CloseRootKeyEx(hRootKey);

	return dw;
}

int CRegistry::ReadInt(LPCTSTR strName, int nDefault)
{
	DWORD dwType = REG_BINARY;
	int n;
	DWORD dwSize = sizeof(n);
	HKEY hKey, hRootKey = GetRootKeyEx();

	ASSERT(m_strCurrentPath.GetLength() > 0);
	REGSAM desire = KEY_READ;
	if ( m_bUseWwow64 )
	{
		desire |= KEY_WOW64_64KEY;
	}
	if ( ::RegOpenKeyEx(hRootKey, LPCTSTR(m_strCurrentPath), 0, desire, &hKey) != ERROR_SUCCESS )
	{
		CloseRootKeyEx(hRootKey);
		return nDefault;
	}

	if (::RegQueryValueEx(hKey, strName, NULL, &dwType, (LPBYTE)&n, &dwSize) != ERROR_SUCCESS )
	{
		n = nDefault;
	}

	::RegCloseKey(hKey);
	CloseRootKeyEx(hRootKey);
	return n;
}

BOOL CRegistry::ReadBool(LPCTSTR strName, BOOL bDefault)
{
	DWORD dwType = REG_DWORD;
	BOOL b;
	DWORD dwSize = sizeof(b);
	HKEY hKey, hRootKey = GetRootKeyEx();

	ASSERT(m_strCurrentPath.GetLength() > 0);
	REGSAM desire = KEY_READ;
	if ( m_bUseWwow64 )
	{
		desire |= KEY_WOW64_64KEY;
	}
	if ( ::RegOpenKeyEx(hRootKey, LPCTSTR(m_strCurrentPath), 0, desire, &hKey) != ERROR_SUCCESS )
	{
		CloseRootKeyEx(hRootKey);
		return bDefault;
	}

	if ( ::RegQueryValueEx(hKey, LPCTSTR(strName), NULL, &dwType, (LPBYTE)&b, &dwSize) != ERROR_SUCCESS )
	{
		b = bDefault;
	}

	::RegCloseKey(hKey);
	CloseRootKeyEx(hRootKey);
	return b;
}

BOOL CRegistry::WriteBinary(LPCTSTR lpszEntry, LPBYTE pData, UINT nBytes)
{
	ASSERT(m_strCurrentPath.GetLength() > 0);
	ASSERT(lpszEntry != NULL);

	if ( lpszEntry != NULL )
	{
		HKEY hKey, hRootKey = GetRootKeyEx();
		REGSAM desire = KEY_WRITE;
		if ( m_bUseWwow64 )
		{
			desire |= KEY_WOW64_64KEY;
		}
		LONG lResult = ::RegOpenKeyEx(hRootKey, LPCTSTR(m_strCurrentPath), 0, desire, &hKey);

		if ( lResult == ERROR_SUCCESS )
		{
			lResult = RegSetValueEx(hKey, lpszEntry, NULL, REG_BINARY, pData, nBytes);
		}

		if ( !m_bLazyWrite )
		{
			::RegFlushKey(hKey);
		}

		RegCloseKey(hKey);
		CloseRootKeyEx(hRootKey);
		return lResult == ERROR_SUCCESS;
	}

	return FALSE;
}

BOOL CRegistry::WriteBool(LPCTSTR strName, BOOL bValue)
{
	ASSERT(m_strCurrentPath.GetLength() > 0);
	BOOL bSuccess = TRUE;
	HKEY hKey, hRootKey = GetRootKeyEx();
	REGSAM desire = KEY_WRITE;
	if ( m_bUseWwow64 )
	{
		desire |= KEY_WOW64_64KEY;
	}
	if ( ::RegOpenKeyEx(hRootKey, LPCTSTR(m_strCurrentPath), 0, desire, &hKey) != ERROR_SUCCESS )
	{
		CloseRootKeyEx(hRootKey);
		return FALSE;
	}
	
	if ( ::RegSetValueEx(hKey, strName, 0, REG_DWORD, (LPBYTE)&bValue, sizeof(bValue)) != ERROR_SUCCESS )
	{
		bSuccess = FALSE;
	}
		
	if ( !m_bLazyWrite )
	{
		::RegFlushKey(hKey);
	}

	::RegCloseKey(hKey);
	CloseRootKeyEx(hRootKey);
	return bSuccess;
}

BOOL CRegistry::WriteString(LPCTSTR strName, LPCTSTR strValue)
{
	ASSERT(m_strCurrentPath.GetLength() > 0);
	BOOL bSuccess = TRUE;
	HKEY hKey;

	int nSize = (_tcslen(strValue) + 1)*sizeof(TCHAR);
	TCHAR* sz = (TCHAR*) malloc( nSize );
	if ( sz == NULL )
	{
		return FALSE;
	}

	sz[_tcslen(strValue)] = 0;
	_tcscpy_s(sz, (nSize)/sizeof(TCHAR), (LPCTSTR)strValue);

	HKEY hRootKey = GetRootKeyEx();
	REGSAM desire = KEY_WRITE;
	if ( m_bUseWwow64 )
	{
		desire |= KEY_WOW64_64KEY;
	}
	if ( ::RegOpenKeyEx(hRootKey, LPCTSTR(m_strCurrentPath), 0, desire, &hKey) != ERROR_SUCCESS )
	{
		free(sz);
		CloseRootKeyEx(hRootKey);
		return FALSE;
	}

	if ( ::RegSetValueEx(hKey, strName, 0, REG_SZ, (LPBYTE)sz, (DWORD)((_tcslen(sz) + 1)*sizeof(TCHAR))) != ERROR_SUCCESS )
	{
		bSuccess = FALSE;
	}
		
	if (!m_bLazyWrite)
	{
		::RegFlushKey(hKey);
	}
	::RegCloseKey(hKey);
	CloseRootKeyEx(hRootKey);
	free(sz);
	return bSuccess;
}

BOOL CRegistry::Write64bit(LPCTSTR strName, __int64 Value64)
{
	ASSERT(m_strCurrentPath.GetLength() > 0);
	BOOL bSuccess = TRUE;
	HKEY hKey, hRootKey = GetRootKeyEx();

	REGSAM desire = KEY_WRITE;
	if ( m_bUseWwow64 )
	{
		desire |= KEY_WOW64_64KEY;
	}
	if ( ::RegOpenKeyEx(hRootKey, LPCTSTR(m_strCurrentPath), 0, desire, &hKey) != ERROR_SUCCESS )
	{
		CloseRootKeyEx(hRootKey);
		return FALSE;
	}

	if ( ::RegSetValueEx(hKey, strName, 0, REG_BINARY, (LPBYTE)&Value64, sizeof(Value64)) != ERROR_SUCCESS )
	{
		bSuccess = FALSE;
	}

	if ( !m_bLazyWrite )
	{
		::RegFlushKey(hKey);
	}

	::RegCloseKey(hKey);
	CloseRootKeyEx(hRootKey);
	return bSuccess;
}

BOOL CRegistry::WriteFloat(LPCTSTR strName, double fValue)
{
	ASSERT(m_strCurrentPath.GetLength() > 0);
	BOOL bSuccess = TRUE;
	HKEY hKey, hRootKey = GetRootKeyEx();

	REGSAM desire = KEY_WRITE;
	if ( m_bUseWwow64 )
	{
		desire |= KEY_WOW64_64KEY;
	}
	if ( ::RegOpenKeyEx(hRootKey, LPCTSTR(m_strCurrentPath), 0, desire, &hKey) != ERROR_SUCCESS )
	{
		CloseRootKeyEx(hRootKey);
		return FALSE;
	}
	
	if ( ::RegSetValueEx(hKey, strName, 0, REG_BINARY, (LPBYTE)&fValue, sizeof(fValue)) != ERROR_SUCCESS )
	{
		bSuccess = FALSE;
	}
		
	if ( !m_bLazyWrite )
	{
		::RegFlushKey(hKey);
	}

	::RegCloseKey(hKey);
	CloseRootKeyEx(hRootKey);
	return bSuccess;
}

BOOL CRegistry::WriteInt(LPCTSTR strName, int nValue)
{
	ASSERT(m_strCurrentPath.GetLength() > 0);
	BOOL bSuccess = TRUE;
	HKEY hKey, hRootKey = GetRootKeyEx();

	REGSAM desire = KEY_WRITE;
	if ( m_bUseWwow64 )
	{
		desire |= KEY_WOW64_64KEY;
	}
	if ( ::RegOpenKeyEx(hRootKey, LPCTSTR(m_strCurrentPath), 0, desire, &hKey) != ERROR_SUCCESS )
	{
		CloseRootKeyEx(hRootKey);
		return FALSE;
	}
	
	if ( ::RegSetValueEx(hKey, strName, 0, REG_BINARY, (LPBYTE)&nValue, sizeof(nValue)) != ERROR_SUCCESS )
	{
		bSuccess = FALSE;
	}
		
	if ( !m_bLazyWrite )
	{
		::RegFlushKey(hKey);
	}

	::RegCloseKey(hKey);
	CloseRootKeyEx(hRootKey);
	return bSuccess;
}

BOOL CRegistry::WriteDword(LPCTSTR strName, DWORD dwValue)
{
	ASSERT(m_strCurrentPath.GetLength() > 0);
	BOOL bSuccess = TRUE;
	HKEY hKey, hRootKey = GetRootKeyEx();

	REGSAM desire = KEY_WRITE;
	if ( m_bUseWwow64 )
	{
		desire |= KEY_WOW64_64KEY;
	}
	if ( ::RegOpenKeyEx(hRootKey, LPCTSTR(m_strCurrentPath), 0, desire, &hKey) != ERROR_SUCCESS )
	{
		CloseRootKeyEx(hRootKey);
		return FALSE;
	}
	
	if ( ::RegSetValueEx(hKey, strName, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue)) != ERROR_SUCCESS )
	{
		bSuccess = FALSE;
	}
		
	if ( !m_bLazyWrite )
	{
		::RegFlushKey(hKey);
	}

	::RegCloseKey(hKey);
	CloseRootKeyEx(hRootKey);
	return bSuccess;
}
